/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.minidota.db;

import java.sql.*;

/**
 *
 * @author Fedor
 */
public class Db {

    /**
     *
     * @return Connection БД
     * @throws SQLException
     */
    public Connection getConnection() throws SQLException {
        return Connector.getConnection();
    }

    /**
     *
     * @param conn
     * @param cs
     * @param rs
     */
    public static void closeConnection(Connection conn, CallableStatement cs, ResultSet rs) {
        closeConnection(conn, null, null, rs, cs);
    }

    /**
     *
     * @param conn
     * @param ps
     * @param rs
     */
    public static void closeConnection(Connection conn, PreparedStatement ps, ResultSet rs) {
        closeConnection(conn, ps, null, rs, null);
    }

    /**
     * Закрывает все что было не закрыто
     * @param conn
     * @param ps
     * @param st
     * @param rs
     * @param cs
     */
    public static void closeConnection(Connection conn, PreparedStatement ps, Statement st, ResultSet rs, CallableStatement cs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (Exception ex) {
            System.out.println("ResultSet not closed: " + ex);
        }
        try {
            if (ps != null) {
                ps.close();
            }
        } catch (Exception ex) {
            System.out.println("PrepareStatement not closed: Exception: " + ex);
        }
        try {
            if (cs != null) {
                cs.close();
            }
        } catch (Exception ex) {
            System.out.println("CallableStatement not closed: Exception: " + ex);
        }
        try {
            if (st != null) {
                st.close();
            }
        } catch (Exception ex) {
            System.out.println("Statement not closed: Exception: " + ex);
        }
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (Exception ex) {
            System.out.println("Connection not closed: " + ex);
        }
    }

    /**
     * Возвращет количество записей для части sql
     * или -1 если ни чего не нашлось
     * @param sql String - строка после
     * SELECT count(*) FROM
     * @return long зачение count
     */
    public static long count(String sql) {
        sql = "SELECT count(*) FROM " + sql;
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        long res = -1;
        try {
            connection = Connector.getConnection();
            ps = connection.prepareStatement(sql);
            rs = ps.executeQuery();
            if (rs != null && rs.next()) {
                res = rs.getLong(1);
            }
        } catch (SQLException ex) {
            System.out.println("SQLException: " + ex + " sql: " + sql);
        } finally {
            closeConnection(connection, ps, rs);
        }
        return res;
    }

    /**
     * Возвращет long
     * или -1 если ни чего не нашлось
     * @param ps PreparedStatement
     * @return long или -1
     */
    public static long count(PreparedStatement ps) {
        ResultSet rs = null;
        long res = -1;
        try {
            rs = ps.executeQuery();
            if (rs != null && rs.next()) {
                res = rs.getLong(1);
            }
        } catch (SQLException ex) {
            System.out.println("Exception: " + ex);
        } finally {
            closeConnection(null, ps, rs);
        }
        return res;
    }

    /**
     * Добавляет sql в базу
     * @param sql String для вставки в базу
     * @return true если executeUpdate вернул больше 0
     */
    public static boolean insert(String sql) {
        boolean res = false;
        PreparedStatement ps = null;
        Connection connection = null;
        try {
            connection = Connector.getConnection();
            ps = connection.prepareStatement(sql);
            res = ps.executeUpdate() > 0;
        } catch (SQLException ex) {
            System.out.println("SQLException: " + sql + " " + ex);
        } finally {
            closeConnection(connection, ps, null);
        }
        return res;
    }

    /**
     * Добавляет PreparedStatement в базу и
     * возвращает false если executeUpdate свалился
     * @param ps PreparedStatement
     * @return boolean
     */
    public static boolean insert(PreparedStatement ps) {
        boolean res = false;
        try {
            if (ps.executeUpdate() > 0) {
                res = true;
            }
        } catch (SQLException ex) {
            System.out.println("SQLException: " + ex);
        } finally {
            closeConnection(null, ps, null);
        }
        return res;
    }

    /**
     * Достает Object из базы, для каста в любой тип
     * @param ps PreparedStatement
     * @return Object или null если что-то не так
     */
    public static Object selectValue(PreparedStatement ps) {
        Object res = null;
        ResultSet rs = null;
        try {
            rs = ps.executeQuery();
            res = rs.getObject(1);
        } catch (SQLException ex) {
            System.out.println("SQLException: " + ex);
        } finally {
            closeConnection(null, ps, rs);
        }
        return res;
    }

    /**
     * Достает строку из первого столбца ResultSet'а из базы, используя переданный sql
     * @param sql String запрос
     * @return результат запроса из первого столбца
     */
    public static String selectValue(String sql) {

        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        String res = "";
        try {
            connection = Connector.getConnection();
            ps = connection.prepareStatement(sql);
            rs = ps.executeQuery();
            if (rs != null && rs.next()) {
                res = rs.getString(1);
            }
        } catch (SQLException ex) {
            System.out.println("SQLException: " + sql + " " + ex);
        } finally {
            closeConnection(connection, ps, rs);
        }
        return res;
    }

    /**
     * Достает long из первого столбца ResultSet'а из базы, используя переданный sql
     * @param sql String запрос
     * @return результат запроса из первого столбца или -1L
     */
    public static long selectLongValue(String sql) {
        Connection connection = null;
        PreparedStatement ps = null;
        long res = -1;
        try {
            connection = Connector.getConnection();
            ps = connection.prepareStatement(sql);
            res = selectLongValue(ps);
        } catch (SQLException ex) {
            System.out.println("SQLException: " + sql + " " + ex);
        } finally {
            closeConnection(connection, ps, null);
        }
        return res;
    }

    /**
     * Достает long из первого столбца ResultSet'а из базы, используя переданный sql
     * @param ps PreparedStatement запрос
     * @return результат запроса из первого столбца или -1L
     */
    public static long selectLongValue(PreparedStatement ps) {
        long res = -1;
        ResultSet rs = null;
        try {
            rs = ps.executeQuery();
            if (rs.next()) {
                res = rs.getLong(1);
            }
        } catch (SQLException ex) {
            System.out.println("SQLException: " + ex);
        } finally {
            closeConnection(null, ps, rs);
        }
        return res;
    }

    /**
     * Выполняет executeUpdate для sql
     * @param sql String запрос
     * @return количество затронутых строк
     */
    public static long execute(String sql) {
        Connection connection = null;
        PreparedStatement ps = null;
        long res = -1;
        try {
            connection = Connector.getConnection();
            ps = connection.prepareStatement(sql);
            res = ps.executeUpdate();
        } catch (SQLException ex) {
            System.out.println("SQLException: " + sql + " " + ex);
        } finally {
            closeConnection(connection, ps, null);
        }
        return res;
    }
}
